FlamingLoot = LibStub("AceAddon-3.0"):NewAddon("FlamingLoot", "AceConsole-3.0", "AceEvent-3.0")

--VARIABLES
local lootTable = {}
local currentitem = 1
local lootcount = 0
local rollingopen = false
local playerclass = UnitClass("player")
local optsdisplay = {
	["n"] = "need",
	["i"] = "minor upgrade",
	["s"] = "sidegrade",
	["o"] = "offspec",
	["g"] = "greed",
	["p"] = "pass",
}
local fra = CreateFrame("Frame", "FLR_ItemCachingFrame")
local interval = 0

local defaults = {
	profile = {
		masterlooter = "masterlooter",
		standings = "no standings stored",
		standingstime = 0,
		balance = 0,
		balupdate = "never!",
		playertoken = nil,
	},
}

local commands = {
	standings = {
		desc = "View standings.  Can also be accessed with |cffffff78/fls|r",
		func = function() FlamingLoot:ShowStandings() end,
	},
	update = {
		desc = "Update your standings.  Only use this if you missed a raid or part of one - standings are automatically broadcast to the raid whenever they are updated.  Requires your masterlooter to be online.",
		func = function() FlamingLoot:GetStandings() end,
	},
	balance = {
		desc = "View your current balance with regard to raid expenses.",
		func = function() FlamingLoot:Balance(true) end,
	},
}


--INITIALIZE & ENABLE
function FlamingLoot:OnInitialize()
	RegisterAddonMessagePrefix("flamingloot")
	self.db = LibStub("AceDB-3.0"):New("FlamingLootDB", defaults)
end

function FlamingLoot:OnEnable()
	self:RegisterEvent("CHAT_MSG_ADDON")
	self:RegisterChatCommand("fls", "ShowStandings")
	self:RegisterChatCommand("fl", "ProcessChatCmd")
	FLRaiderStandings:SetScale(0.8)
	FLLootRollFrame:SetScale(0.8)
	FLRaiderStandingsTitle:SetText("Standings")
	if not self.db.profile.playertoken then
		FlamingLoot:SetToken()
	end
end

--MAIN FUNCS
function FlamingLoot:StartLooting(sender, param)
	--format: "item:id=rolltype;"
	FLR_ItemCachingFrame:Show()
	lootcount = 0
	rollingopen = true
	self.db.profile.masterlooter = sender
	for itemid, rollopts in string.gmatch(param, "(%d+)=(%a+);") do
		lootcount = lootcount+1
		if not lootTable[lootcount] then --only make a new table if we haven't already
			lootTable[lootcount] = {}
		end
		lootTable[lootcount]["itemid"] = tonumber(itemid)
		lootTable[lootcount]["rollopts"] = rollopts
		--self:Print("item number "..lootcount.." - id is "..lootTable[lootcount]["itemid"]..", roll opts are "..lootTable[lootcount]["rollopts"]) --DEBUG
	end
end

local done = false	
local function GetLootInfo(self, elapsed)
	interval = interval + elapsed
	if interval>.5 and lootTable[1].itemid then
		done = true
		for i, itemtable in pairs(lootTable) do
			if not lootTable[i].link then 
				--FlamingLoot:Print("looking up item id "..itemtable.itemid)
				local test = GetItemInfo(itemtable.itemid)
				if not test then
					done = false
				else
					itemtable["link"] = (select(2, GetItemInfo(itemtable.itemid)))
					--:Print(lootTable[i].link)
				end
			end
		end
		if done==true then
			--FlamingLoot:Print("done!")
			fra:Hide()
			FlamingLoot:ProcessLoot()
		end
		interval = 0
	end
end
fra:SetScript("OnUpdate", GetLootInfo)
fra:Hide()

function FlamingLoot:ProcessLoot()
	for i=1, lootcount do
		local _, ilink, _, ilvl, _, class, subtype, _, equipSlot, texture, _ = GetItemInfo(lootTable[i].itemid)
		--self:Print("item number "..i.." link is "..ilink..", roll opts "..lootTable[i].rollopts) --debug
		subtype = subtype or class
		lootTable[i]["link"] = ilink
		lootTable[i]["texture"] = texture
		if equipSlot=="INVTYPE_CLOAK" then subtype="Cloak" end
		--self:Print(ilink..class.." "..subtype.." "..equipSlot)
		if string.find(lootTable[i].rollopts, "n") and class~="Recipe" and FlamingLoot:DetermineAutopass(subtype, ilink) then
			lootTable[i].selec = "u"
		end
	end
	FlamingLoot:LootNextItem() 
end

function FlamingLoot:LootNextItem()
	FLLootRollFrameButton3:Hide()
	FLLootRollFrameButton4:Hide()
	if lootTable[currentitem].selec then
		FlamingLoot:RollonItem(lootTable[currentitem].selec)
	else
		local heightmult = 1
		--self:Print(lootTable[currentitem].link.." item num "..currentitem)
		FLLootRollFrameItem:SetScript("OnEnter", function(self, motion) FlamingLoot:ShowTooltip(FLLootRollFrameItem, lootTable[currentitem].link, "ANCHOR_RIGHT") end)
		FLLootRollFrameItem:SetScript("OnLeave", function(self, motion) GameTooltip:Hide() end)
		FLLootRollFrameItem:SetNormalTexture(lootTable[currentitem].texture)
		FLLootRollFrameItemLink:SetText(lootTable[currentitem].link)
		--FLLootRollFrameItemType:SetText(lootTable[currentitem].subtype)
		FLLootRollFrameButton1:SetText(optsdisplay[string.sub(lootTable[currentitem].rollopts, 1, 1)])
		FLLootRollFrameButton1:SetScript("OnClick", function() FlamingLoot:RollonItem(string.sub(lootTable[currentitem].rollopts, 1, 1)) end)
		FLLootRollFrameButton2:SetText(optsdisplay[string.sub(lootTable[currentitem].rollopts, 2, 2)])
		FLLootRollFrameButton2:SetScript("OnClick", function() FlamingLoot:RollonItem(string.sub(lootTable[currentitem].rollopts, 2, 2)) end)
		local opt = string.sub(lootTable[currentitem].rollopts, 3, 3)
		if  opt ~="" then
			heightmult = 2
			FLLootRollFrameButton3:SetText(optsdisplay[opt])
			FLLootRollFrameButton3:SetScript("OnClick", function() FlamingLoot:RollonItem(string.sub(lootTable[currentitem].rollopts, 3, 3)) end)
			FLLootRollFrameButton3:Show()
		end
		opt = string.sub(lootTable[currentitem].rollopts, 4, 4)
		if opt ~="" then
			FLLootRollFrameButton4:SetScript("OnClick", function() FlamingLoot:RollonItem(string.sub(lootTable[currentitem].rollopts, 4, 4)) end)
			FLLootRollFrameButton4:SetText(optsdisplay[opt])
			FLLootRollFrameButton4:Show()
		end
		FLLootRollFrame:SetHeight(70+30*heightmult)
		FLLootRollFrame:Show()
	end
end

function FlamingLoot:RollonItem(button)
	--"item name=rolltype;roll#"
	printstr=""
	lootTable[currentitem].msg = "roll:"..lootTable[currentitem].itemid.."="..button
	if button=="u" then 
		printstr = "Auto-passed on "..lootTable[currentitem].link
	else 
		printstr = "You rolled "..optsdisplay[button].." on "..lootTable[currentitem].link
		local roll = math.random(100)
		if button ~="n" and button ~="p"then
			printstr = printstr.."|cffFFFF00, random roll: "..roll
		end
		lootTable[currentitem].msg = lootTable[currentitem].msg..";"..roll
	end
	self:Print(printstr..".")
	SendAddonMessage("flamingloot", lootTable[currentitem].msg, "WHISPER", self.db.profile.masterlooter);
	FLLootRollFrame:Hide()
	wipe(lootTable[currentitem])
	if currentitem<lootcount then
		currentitem = currentitem+1
		if rollingopen==true then FlamingLoot:LootNextItem() end
	end
end

function FlamingLoot:EndLooting()
	FLLootRollFrame:Hide()
	rollingopen = false
	if currentitem<lootcount then 
		self:Print("Loot rolling closed before you finished rolling.")
	end
	lootcount = 0
	currentitem = 1
	wipe(lootTable)
end

--STANDINGS
function FlamingLoot:ShowStandings()
	if not FLRaiderText:GetText() then
		FLRaiderText:SetText(self.db.profile.standings.."\n\nupdated "..date("%m/%d %I:%M%p", self.db.profile.standingstime))
	end
	FLRaiderStandings:Show()
end

function FlamingLoot:GetStandings()
	if time()-self.db.profile.standingstime>30 then
		SendAddonMessage("flamingsys", "standings:"..self.db.profile.standingstime, "WHISPER", self.db.profile.masterlooter)
	else
		self:Print("Please wait at least 30s between updates")
	end
end

function FlamingLoot:StandingsRecd(standings)
	FLRaiderText:SetText(standings.."\n\nupdated "..date("%m/%d %I:%M%p", time()))
	self.db.profile.standingstime=time()
	self.db.profile.standings = standings
end

--EXPENSES
function FlamingLoot:Balance(announce, balance, amount)
	if balance then
		self.db.profile.balance = balance
		self.db.profile.balupdate = date("%m/%d %H:%M", time())
	end
	if announce then
		local printstr = ""
		if amount then
			printstr = "Payment of "..amount.."g received.  "
		end
		if self.db.profile.balance<0 then
			printstr=printstr.."You are ahead on payments by "..-self.db.profile.balance.."g."
		else
			printstr=printstr.."You owe "..self.db.profile.balance.."g."
		end
		self:Print(printstr, true)
	end
end

--ADDON MESSAGE HANDLER
function FlamingLoot:ProcessChatCmd(input)
	if not input or input:trim() == "" then
		local commandstr="|cffffff78/fl|r commands:\n"
		for name, t in pairs(commands) do
			commandstr = commandstr.."|cffffff78"..name.."|r - "..t.desc.."\n"
		end
		self:Print(commandstr, true)
	elseif commands[input] then
		commands[input].func()
	else
		self:Print("Not a valid command. Type /fl to view a list of commands", true)
	end
end

function FlamingLoot:CHAT_MSG_ADDON(event, prefix, message, channel, sender)
	if (prefix == "flamingloot") then
		local msgtype = string.match(message, "(%a+):")
		local content = string.match(message, ":(.+)")
		if msgtype == "loot" then
			FlamingLoot:StartLooting(sender, content)
		elseif msgtype =="end" then
			FlamingLoot:EndLooting()
		elseif msgtype=="standings" then
			FlamingLoot:StandingsRecd(content)
		elseif msgtype=="version" then
			FlamingLoot:VersionCheck(tonumber(content), sender)
		elseif msgtype=="uptodate" then
			FlamingLoot:Print("Your standings are up to date.", true)
			self.db.profile.standingstime=time()
		elseif msgtype=="balance" then
			FlamingLoot:Balance(false, tonumber(content))
		elseif msgtype=="payment" then
			local payment, balance = string.match(content, "(%d+);(.+)")
			FlamingLoot:Balance(true, tonumber(balance), tonumber(payment))
		elseif msgtype=="print" then
			FlamingLoot:Print(content, true)
		end
	end
end

--UTILITY FUNCS/LOOKUPS
function FlamingLoot:Print(text, pref)
	if text then
		if pref then
			DEFAULT_CHAT_FRAME:AddMessage("  ff6600FFfl:|r "..tostring(text))
		else
			DEFAULT_CHAT_FRAME:AddMessage("|cffFFFF00 "..tostring(text))
		end
	end
end

function FlamingLoot:VersionCheck(sentvers, sender) --TEST
	local vers = GetAddOnMetadata("flamingloot", "Version")
	local one, two, three = string.match(vers, "(%d).*(%d).*(%d)")
	if one and two and three then
		vers = tonumber(one..two..three)
		if vers<sentvers then
			self:Print("A newer version of flaming loot is available.  Visit curse.com/addons/wow/flaming to download.")
		elseif vers>sentvers then
			SendAddonMessage("flamingloot", "print:"..GetUnitName("player").." has a newer version of flaming loot than you.  Visit curse.com/addons/wow/flaming to update.", "WHISPER", sender)
		end
	end
end

local disallowed = { --modified from LibGearPoints-1.2 (EPGP)
	["Death Knight"] = {
		Leather = true,
		Mail = true,
		Cloth = true,
		Shields = true,
		Bows = true,
		Crossbows = true,
		Daggers = true,
		["Fist Weapons"] = true,
		Guns = true,
		Polearms = true,
		Staves = true,
		Idols = true,
		Librams = true,
		Thrown = true,
		Totems = true,
		Wands = true,
	},
	Druid = {
		Cloth = true,
		Mail = true,
		Plate = true,
		Plate = true,
		Shields = true,
		Bows = true,
		Crossbows = true,
		Guns = true,
		["One-Handed Axes"] = true,
		["One-Handed Swords"] = true,
		["Two-Handed Axes"] = true,
		["Two-Handed Swords"] = true,
		Librams = true,
		Sigils = true,
		Thrown = true,
		Totems = true,
		Wands = true,
	},
	Hunter= {
		Leather = true,
		Cloth = true,
		Plate = true,
		Shields = true,
		["One-Handed Maces"] = true,
		["Two-Handed Maces"] = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Totems = true,
		Wands = true,
	},
	Mage = {
		Leather = true,
		Mail = true,
		Plate = true,
		Shields = true,
		Bows = true,
		Crossbows = true,
		["Fist Weapons"] = true,
		Guns = true,
		["One-Handed Axes"] = true,
		["One-Handed Maces"] = true,
		Polearms = true,
		["Two-Handed Axes"] = true,
		["Two-Handed Maces"] = true,
		["Two-Handed Swords"] = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Thrown = true,
		Totems = true,
	},
	Paladin = {
		Leather = true,
		Mail = true,
		Cloth = true,
		Bows = true,
		Crossbows = true,
		["Fist Weapons"] = true,
		Guns = true,
		Staves = true,
		Idols = true,
		Sigils = true,
		Thrown = true,
		Totems = true,
		Wands = true,
	},
	Priest = {
		Leather = true,
		Mail = true,
		Plate = true,
		Shields = true,
		Bows = true,
		Crossbows = true,
		["Fist Weapons"] = true,
		Guns = true,
		["One-Handed Axes"] = true,
		["One-Handed Swords"] = true,
		Polearms = true,
		["Two-Handed Axes"] = true,
		["Two-Handed Maces"] = true,
		["Two-Handed Swords"] = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Thrown = true,
		Totems = true,
	},
	Rogue = {
		Cloth = true,
		Mail = true,
		Plate = true,
		Shields = true,
		Polearms = true,
		Staves = true,
		["Two-Handed Axes"] = true,
		["Two-Handed Maces"] = true,
		["Two-Handed Swords"] = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Totems = true,
		Wands = true,
		},
	Shaman = {
		Plate = true,
		Leather = true,
		Cloth = true,
		Bows = true,
		Crossbows = true,
		Guns = true,
		["One-Handed Swords"] = true,
		Polearms = true,
		["Two-Handed Swords"] = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Thrown = true,
		Wands = true,
	},
	Warlock = {
		Leather = true,
		Mail = true,
		Plate = true,
		Shields = true,
		Bows = true,
		Crossbows = true,
		["Fist Weapons"] = true,
		Guns = true,
		["One-Handed Axes"] = true,
		["One-Handed Maces"] = true,
		Polearms = true,
		["Two-Handed Axes"] = true,
		["Two-Handed Maces"] = true,
		["Two-Handed Swords"] = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Thrown = true,
		Totems = true,
	},
	Warrior = {
		Leather = true,
		Mail = true,
		Cloth = true,
		Idols = true,
		Librams = true,
		Sigils = true,
		Totems = true,
		Wands = true,
   },
 }

local PRIMARY_STAT = {
	Strength = {
		["Death Knight"] = true,
		Paladin = true,
		Warrior = true,
	},
	Agility = {
		Druid = true,
		Hunter = true,
		Rogue = true,
		Shaman = true,
	},
	Intellect  = {
		Mage = true,
		Priest = true,
		Shaman = true,
		Warlock = true,
		Paladin = true,
		Druid = true,
	},
}

function FlamingLoot:NotMainStat(link) --adapted from LibItemUtils-1.0 (EPGP)
	FLScanningTooltip:SetOwner(UIParent, "ANCHOR_NONE")
	FLScanningTooltip:SetHyperlink(link)
	local section
	local stat
	for i=4, FLScanningTooltip:NumLines()-3 do
		section = getglobal("FLScanningTooltipTextLeft"..i)
		stat = string.match(section:GetText(), "%d+%s(%a+)")
		if stat and PRIMARY_STAT[stat] then
			return not PRIMARY_STAT[stat][playerclass]
		end
	end
	return false
end

function FlamingLoot:UnusableArmorToken(subtype, link)
	if subtype=="Junk" and string.match(link, "of the %a+ %a+") then --is a token
		if string.match(link, self.db.profile.playertoken) then
			return false
		else
			return true
		end
	end
	return false
end

function FlamingLoot:DetermineAutopass(subtype, link) --returns true if autopass, false if not
	if subtype and disallowed[playerclass][subtype] then
		return true
	elseif FlamingLoot:NotMainStat(link) then
		return true
	elseif FlamingLoot:UnusableArmorToken(subtype, link) then
		return true
	else
		return false
	end
end

function FlamingLoot:SetToken()
	if playerclass == "Mage" or playerclass == "Druid" or playerclass == "Death Knight" or playerclass == "Rogue" then
		self.db.profile.playertoken = "Vanquisher"
	elseif playerclass == "Paladin" or playerclass == "Warlock" or playerclass == "Priest" then
		self.db.profile.playertoken = "Conqueror"
	elseif playerclass == "Hunter" or playerclass == "Shaman" or playerclass == "Warrior" then
		self.db.profile.playertoken = "Protector"
	end
end

function FlamingLoot:TextTooltip(owner, text)
	GameTooltip:SetOwner(owner, "ANCHOR_RIGHT")
	GameTooltip:SetText(text)
	GameTooltip:Show()
end

function FlamingLoot:ShowTooltip(owner, itemlink, position)
	GameTooltip:SetOwner(owner, position)
	GameTooltip:SetHyperlink(itemlink)
	GameTooltip:Show()
end